﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ChartEdit
{
    public enum beatType : byte
    {
        NotABeat = 255,
        SixteenthBeat = 0,
        EighthBeat = 1,
        QuarterBeat = 2,
        HalfBeat = 3,
        Beat = 4,
        Measure = 5
    }
    public class TSManager
    {
        private List<int> tSInd;
        private List<beatType> beat;
        private int lastTSOffset;
        private int lastTS;
        private Chart chart;

        public void DetectTimeSignatures(SyncTrackSection sT)
        {
            beat.Clear();//clear the damn beats

            int i = 0;//index
            tSInd = new List<int>();
            int tS;//timesignature
            int tSOffset;
            int Offset;
            int nextTS;
            //find the tS indexes into a list so I'm not in hell while coding this
            for (i = 0; i < sT.Count; i++)
            {
                if (sT[i].Type == SyncType.TimeSignature)
                {
                    tSInd.Add(i);
                }
            }
            //Find line types now
            for (i = 0; i < tSInd.Count; i++)
            {
                tS = sT[tSInd[i]].TimeSignature;
                tSOffset = sT[tSInd[i]].Offset;
                if (tSInd.Count == i + 1)
                {
                    beat.Add(beatType.Measure);
                    lastTSOffset = tSOffset;
                    lastTS = tS;
                    break;
                }

                nextTS = sT[tSInd[i + 1]].Offset;
                for (Offset = tSOffset; Offset < nextTS; Offset += chart.HalfResolution)
                {
                    int o = Offset - tSOffset;
                    #region Add Measure Types
                    if (o % (chart.Resolution * tS) == 0)
                    {
                        beat.Add(beatType.Measure);//Measure
                        continue;
                    }
                    if (o % chart.Resolution == 0)
                    {
                        beat.Add(beatType.Beat);//Beat (1/4 notes)
                        continue;
                    }
                    if (o % chart.HalfResolution == 0)
                    {
                        beat.Add(beatType.HalfBeat);//HalfBeat (1/8 notes)
                        continue;
                    }
                    if (o % chart.QuarterResolution == 0)
                    {
                        beat.Add(beatType.QuarterBeat);//QuarterBeat (1/16 notes)
                        continue;
                    }
                    if (o % chart.EighthResolution == 0)
                    {
                        beat.Add(beatType.EighthBeat);//QuarterBeat (1/32 notes)
                        continue;
                    }
                    if (o % chart.SixteenthResolution == 0)
                    {
                        beat.Add(beatType.SixteenthBeat);//QuarterBeat (1/64 notes)
                        continue;
                    }
                    beat.Add(beatType.NotABeat);
                    #endregion

                }

            }
        }

        public beatType this[int offset]
        {
            get
            {
                if (offset % chart.HalfResolution != 0 | offset < 0)
                    return beatType.NotABeat;
                if (offset / chart.HalfResolution < beat.Count)
                    return beat[offset / chart.HalfResolution];
                else
                {
                    #region ARRRRRGGGGGGGGGGGGGGGGGGGHHHHHHH
                    int o = offset - lastTSOffset;
                    if (o % (chart.Resolution * lastTS) == 0)
                        return beatType.Measure;
                    if (o % chart.Resolution == 0)
                        return beatType.Beat;
                    if (o % chart.HalfResolution == 0)
                        return beatType.HalfBeat;
                    if (o % chart.QuarterResolution == 0)
                        return beatType.QuarterBeat;
                    if (o % chart.EighthResolution == 0)
                        return beatType.EighthBeat;
                    if (o % chart.SixteenthResolution == 0)
                        return beatType.SixteenthBeat;
                    return beatType.NotABeat;
                    #endregion
                }
            }
        }

        public int NearestSnapPointBeat(int snapResolution, int offset)
        {
            SyncTrackSection sT = chart.SyncTrack;
            int bOffset=0;
            if (offset > lastTSOffset)
                bOffset = lastTSOffset;
            else
            {
                foreach (int i in tSInd)
                {
                    if (sT[i].Offset < offset)
                        bOffset = sT[i].Offset;
                }
            }

            bOffset += ((offset-bOffset) / snapResolution) * snapResolution;
            for(int i=0;;i+=snapResolution)
            {
                if( Math.Abs(offset-(bOffset+i)) >
                    Math.Abs(offset-(bOffset+i-snapResolution)) )
                    return bOffset + i - snapResolution;
            }
        }


        public TSManager(Chart chart)
        {
            beat = new List<beatType>();
            this.chart = chart;
            DetectTimeSignatures(chart.SyncTrack);
        }
    }
}
